<template>
  <div class="tree-select-input">
    <!-- 此处为了自定义显示选中后内容，盖在真实的select上面 -->
    <a-form-item-rest>
      <a-input
        id="tree-select-hidden-input"
        v-model:value="showLabel"
        :class="inputClass"
        :placeholder="placeholder ? placeholder : '请选择'"
      ></a-input>
    </a-form-item-rest>
    <a-tree-select
      v-model:value="selectValue"
      :class="selectClass"
      style="width: 100%"
      :placeholder="placeholder ? placeholder : '请选择'"
      :dropdown-class-name="dropdownClassName"
      :dropdown-style="dropdownStyle"
      :dropdown-match-select-width="false"
      allow-clear
      :tree-data="treeData"
      :field-names="fieldNames"
      :get-popup-container="getPopupContainer"
      :size="size"
      :tree-node-label-prop="fullLabel"
      :tree-default-expanded-keys="treeDefaultExpandedKeys"
      @change="(e, label, extra) => handleChange(e, label, extra)"
    >
      <template #title="record">
        <div
          v-if="isDisabled(record)"
          class="overflow-hidden"
          style="color: rgba(0, 0, 0, 0.25); cursor: not-allowed"
          @click.stop
        >
          {{ record[fieldNames.label] }}
        </div>
        <div v-else class="overflow-hidden">{{ record[fieldNames.label] }}</div>
      </template>
    </a-tree-select>
  </div>
</template>
<script lang="ts" setup>
import { feeTypeSelectByContractType } from '@@/api/finance/contract'
import { getAmountTypeList } from '@@/api/finance/payRegisterAndReceived'
import { getExpensesTypeList } from '@@/api/finance/expensesType'
import { ref, toRef, computed } from 'vue'
const emits = defineEmits(['update:value', 'update:name', 'change'])

const props = withDefaults(
  defineProps<{
    isHttps?: boolean // 是否要请求接口获取数据
    httpUrl?: string // 请求接口时候的接口key
    params?: any // 请求接口的时候的入参
    dataList?: any // tree的数据
    value: any // 双向绑定的值
    fieldNames?: any // 下拉框显示的options
    dropdownStyle?: any // dropdown的内置样式
    getPopupContainer?: any // 菜单渲染父节点
    currentId?: any // 修改的时候，当前选中的值，为了去做禁用区分
    disabledArr?: string[] // 禁用的id数组
    placeholder?: string // placeholder
    dropdownClassName?: string // 下拉树的class
    size?: 'small' | 'middle' | 'large' | undefined
    fullLabel?: string // 此处为title的显示字段，和替换的input的显示字段，如果显示字段不是fullFeeTypeName，需要必传
    isReady?: boolean // 数据是传入的时候，判断是否加载完成
    fullIdKey?: string // 该字段是所有的父节点id的键，用于默认展开使用，如果字段不是 fullFeeTypeId ，需要必传
    inputClass?: string // 盖select的input的class
    selectClass?: string
  }>(),
  {
    isHttps: true,
    httpUrl: 'feeTypeTree',
    params: {},
    dataList: [],
    value: undefined,
    fieldNames: {
      children: 'children',
      label: 'feeTypeName',
      value: 'feeTypeConfigId'
    },
    dropdownStyle: { maxHeight: '400px', overflow: 'auto' },
    getPopupContainer: undefined,
    currentId: undefined,
    disabledArr: undefined,
    placeholder: '请选择',
    dropdownClassName: 'dropdownTreeSelect',
    size: undefined,
    fullLabel: 'fullFeeTypeName',
    isReady: false,
    fullIdKey: 'fullFeeTypeId',
    inputClass: '',
    selectClass: ''
  }
)
const selectValue = ref<any>(props.value)
const fnUrl = {
  feeTypeTree: feeTypeSelectByContractType,
  commonFinance: getAmountTypeList,
  orgTypeTreeList: getExpensesTypeList
}
const isDisabled = (record) => {
  return (
    (record.disable || (props.disabledArr && props.disabledArr.includes(record[props.fieldNames.value]))) &&
    props.currentId !== record[props.fieldNames.value]
  )
}
const getInfo = () => {
  fnUrl[props.httpUrl](props.params).then((res) => {
    treeData.value = res
    getTreeDataFlag.value = true
  })
}
const getTreeDataFlag = ref<boolean>(false) // 用于判断是否已经取了数据
let treeData = ref([])
if (props.isHttps) {
  getInfo()
} else {
  treeData = toRef(props, 'dataList')
}

const handleChange = (e, _label, extra) => {
  let name = ''
  if (e) {
    const record: any = getFeeTypeConfigInfo(e, treeData.value)
    name = record[props.fieldNames.label]
    if (isDisabled(record)) {
      selectValue.value = extra.preValue[0]
      return
    }
  }
  emits('update:value', e)
  // change出去的东西
  emits('change', {
    id: e,
    name: name,
    extra
  })
}

// // 获取当前选中的
const getFeeTypeConfigInfo = (id, arr) => {
  let record = {}
  arr = arr || treeData.value || []
  arr.some((item) => {
    if (item[props.fieldNames.value] === id) {
      record = item
      return true
    }
    if (Array.isArray(item[props.fieldNames.children]) && item[props.fieldNames.children].length > 0) {
      record = getFeeTypeConfigInfo(id, item[props.fieldNames.children])
      if (record[props.fieldNames.value]) {
        return true
      }
    }
    return false
  })
  // fullName
  return record
}

const showLabel = computed(() => {
  return computedShowLabel()
})
const computedShowLabel = () => {
  if (getTreeDataFlag.value || (props.isReady && !props.isHttps)) {
    const data = treeData.value || props.dataList
    const record: any = getFeeTypeConfigInfo(props.value, data)
    const label = record[props.fullLabel] || record[props.fieldNames.label]
    // 此处特殊处理：如果选中的数据被删除或者被禁用，手动清空该项，并emits出去
    if (!label && props.value) {
      selectValue.value = undefined
      emits('update:value', undefined)
      // change出去的东西
      emits('change', {
        id: undefined,
        name: undefined
      })
    }
    return label
  }
  return ''
}
// 默认展开到可以选择的那一个层级
const treeDefaultExpandedKeys = computed(() => {
  const keysArr = []
  computedExpandedInfo(treeData.value, keysArr)
  return keysArr
})
const computedExpandedInfo = (data, updateArr) => {
  data.forEach((item) => {
    if (isDisabled(item)) {
      if (Array.isArray(item[props.fieldNames.children]) && item[props.fieldNames.children].length > 0) {
        computedExpandedInfo(item[props.fieldNames.children], updateArr)
      }
    } else {
      // 需要把它自己的id筛选掉，不然它本身也会多余展开
      const arr = item[props.fullIdKey].split(',').filter((i) => i !== item[props.fieldNames.value])
      updateArr.push(...arr)
    }
  })
}
</script>
<style lang="less">
.tree-select-input {
  position: relative;
  #tree-select-hidden-input {
    position: absolute;
    z-index: 2;
    pointer-events: none;
    border: none;
    padding: 3px 11px;
    top: 2px;
    width: calc(100% - 25px);
    left: 2px;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
}
.ant-select-tree-list-scrollbar.ant-select-tree-list-scrollbar-show {
  display: inline-block !important;
}
</style>
